package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;
    @Autowired
    private RabbitService rabbitService;
	@Autowired
	private RedissonClient redissonClient;
	@Autowired
	private RedisTemplate redisTemplate;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
		/*
			需要保存三张信息表，album_info, album_attribute_value, album_stat
		 */
		//	1.	先保存专辑信息表：
		try {
			AlbumInfo albumInfo = new AlbumInfo();
			//	属性赋值: 前提条件是属性名必须一致！
			BeanUtils.copyProperties(albumInfoVo, albumInfo);
			//用户 id
			albumInfo.setUserId(userId);
			//设置试听集数
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
				albumInfo.setTracksForFree(5);
			}
			//	设置审核状态：直接写死
			albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
			albumInfoMapper.insert(albumInfo);
			//	album_attribute_value 保存标签：因为标签是好多种,类似与KV,所以用List集合
			List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
			if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
				//	循环遍历赋值：
				for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
					//	创建对象
					AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
					//	赋值：
					albumAttributeValue.setAlbumId(albumInfo.getId());
					albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
					albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
					albumAttributeValueMapper.insert(albumAttributeValue);
				}
				//	优化进行批量保存！---留作业;
			}
			//	album_stat
			saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
			saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
			saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
			saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);

			if ("1".equals(albumInfo.getIsOpen())){
				//  调用上架方法;
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
				//  将专辑Id添加到布隆过滤器;
				RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
				bloomFilter.add(albumInfo.getId());

			}
		} catch (BeansException e) {
			log.error(e.getMessage(), e);
			throw new GuiguException(ResultCodeEnum.SERVICE_ERROR);
		}
		return true;
	}


	public void saveAlbumStat(Long albumId, String statPlay) {
		//	创建对象
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(albumId);
		albumStat.setStatNum(new Random().nextInt(100000));
		albumStat.setStatType(statPlay);
		albumStatMapper.insert(albumStat);
	}


	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page, AlbumInfoQuery albumInfoQuery) {

		return albumInfoMapper.selectUserAlbumPage(page,albumInfoQuery);
	}

	@Override
	@TsCache(keyPrefix = "album:",keySuffix = ":info")
	public AlbumInfo getAlbumInfo(Long albumId) {
		return getAlbumInfoDB(albumId);
//		//  定义String 数据类型；
//		String dataKey = RedisConstant.ALBUM_INFO_PREFIX + albumId;
//		//  根据缓存的key获取数据;
//		AlbumInfo albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(dataKey);
//		//  判断缓存中是否存在数据;
//		if (null == albumInfo){
//			//  不存在; 查询数据库;
//			//  加锁;
//			String lockKey = RedisConstant.ALBUM_LOCK_SUFFIX + albumId;
//			RLock lock = redissonClient.getLock(lockKey);
//			lock.lock();
//			try {
//				//  业务逻辑;
//				albumInfo = getAlbumInfoDB(albumId);
//			} catch (Exception e) {
//				//  异常信息;
//
//			} finally {
//				//  解锁：
//				lock.unlock();
//			}
//
//		}
//
//		return getAlbumInfoDB(albumId);
	}

	@Nullable
	private AlbumInfo getAlbumInfoDB(Long albumId) {
		//  因为需要给专辑标签赋值; albumAttributeValueVoList
		//  查询专辑信息表;
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//  为了防止空指针
		if (null != albumInfo) {
			//  根据专辑Id获取到标签数据：
			//  select * from album_attribute_value where album_id = 1630 ;
			//  Warpper 构建查询条件的;
			LambdaQueryWrapper<AlbumAttributeValue> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(AlbumAttributeValue::getAlbumId, albumId);
			List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(wrapper);
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
		}
		//  返回数据
		return albumInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
		//更新专辑信息
		//更新标签信息,删除旧的信息,保存新的标签list集合
		AlbumInfo albumInfo = new AlbumInfo();
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setId(albumId);
		albumInfoMapper.updateById(albumInfo);
		//修改标签时,因为无法直接触发控制器,所以不能实时记录修改的信息,所以只能先删除,在新增
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if(!CollectionUtils.isEmpty(albumAttributeValueVoList)){
			for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				//  属性拷贝;
				BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
				albumAttributeValue.setAlbumId(albumId);
				albumAttributeValueMapper.insert(albumAttributeValue);
	}
		}
		//判断当前专辑是公开
		if("1".equals(albumInfo.getIsOpen())){
			//调用上架方法
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId());
			//判断当前专辑id是否添加到布隆过滤器；
			RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumInfo.getId());
		}else {
			//调用下架方法
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumInfo.getId());
		}
	}




	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfo(Long alubmId) {
		//删除三张表信息 , 专辑信息表，专辑标签表，专辑统计表
		albumInfoMapper.deleteById(alubmId);
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,alubmId));
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,alubmId));
	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		//根据用户id查询专辑列表
		LambdaQueryWrapper<AlbumInfo> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(AlbumInfo::getUserId,userId);
		wrapper.orderByDesc(AlbumInfo::getId);
		//因为数据量太多,固进行分页查询
		Page<AlbumInfo> page = new Page<>(1, 100);
		Page<AlbumInfo> infoPage = albumInfoMapper.selectPage(page, wrapper);
		//	返回专辑列表
		return infoPage.getRecords();



	}

	@Override
	@TsCache(keyPrefix = "statVo:")
	public AlbumStatVo getAlbumStatVo(Long albumId) {
		return albumInfoMapper.selectAlbumStatVo(albumId);
	}

}